#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <QScreen>
#include <QRandomGenerator> //随机数
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //获取屏幕大小
    QList<QScreen *> list_screen =  QGuiApplication::screens();  //多显示器
    QRect rect = list_screen.at(0)->geometry();
    sceneWidth = rect.width();
    sceneHeigth = rect.height();

    //设置小图标
    this->setWindowIcon(QIcon(":/res/Title.png"));
    //设置标题
    this->setWindowTitle("MineSweeper");

    //初始化二维数组
    for(int i = 0; i < rowMax; i++)
        for(int j = 0; j < colMax; j++)
            gridArray[i][j] = nullptr;

    //设置 初级 按钮
    connect(ui->actionlevel1, &QAction::triggered, [=](){
        //更新雷数
        mineTotal = level1_mine;
        //删除显示的雷
        this->del_array();
        this->startMine(level1_row, level1_col);
    });
    //设置 中级 按钮
    connect(ui->actionlevel2, &QAction::triggered, [=](){
        //更新雷数
        mineTotal = level2_mine;
        //删除显示的雷
        this->del_array();
        this->startMine(level2_row, level2_col);
    });
    //设置 高级 按钮
    connect(ui->actionlevel3, &QAction::triggered, [=](){
        //更新雷数
        mineTotal = level3_mine;
        //删除显示的雷
        this->del_array();
        this->startMine(level3_row, level3_col);
    });
    //设置 自定义 按钮
    connect(ui->actionlevel4, &QAction::triggered, [=](){
        timer1->stop();
        if(dlog != nullptr)
        {
            delete dlog;
            dlog = nullptr;
        }
        dlog = new Dlog(currentRow, currentCol, mineTotal);
        dlog->setFixedSize(224, 128);
        //dlog->setAttribute(Qt::WA_DeleteOnClose);  //设置关闭对话框后释放内存
        dlog->exec();       //模态对话框
        //如果点击了确定
        if(dlog->isChoose)
        {
            if(dlog->chooseMine >= (dlog->chooseRow * dlog->chooseCol))
                mineTotal = dlog->chooseRow * dlog->chooseCol - 1;
            else
                mineTotal = dlog->chooseMine;

            //删除显示的雷
            this->del_array();
            this->startMine(dlog->chooseRow, dlog->chooseCol);
        }
        if(isStartTimer)
            timer1->start();
    });

    //放置笑脸
    btn_restart = new QPushButton(this);
    QPixmap pix;
    pix.load(":/res/smile.png");
    pix = pix.scaled(mine_wide_height, mine_wide_height);
    //设置按钮图片显示
    btn_restart->setFixedSize(pix.width(), pix.height());
    btn_restart->setIcon(pix);
    btn_restart->setIconSize(QSize(pix.width(), pix.height()));
    //点击笑脸重置游戏
    connect(btn_restart, &QPushButton::clicked, [=](){
        //删除显示的雷
        this->del_array();
        this->startMine(currentRow, currentCol);
        qDebug() << "restart";
    });

    //设置LCD部件
    lcdNum = new QLCDNumber(this);     //显示雷个数
    lcdTime = new QLCDNumber(this);    //显示时间

    //创建定时器
    timer1 = new QTimer(this);
    connect(timer1, &QTimer::timeout, [=](){
        //一秒计时
        lcdTime->display(++timeNum);
    });
    timer2 = new QTimer(this);
    connect(timer2, &QTimer::timeout, [=](){
        for(int i = 0; i < currentRow; i++)
        {
            for(int j = 0; j < currentCol; j++)
            {
                if(gridArray[i][j]->isMine && gridArray[i][j]->isFlag)
                {
                    if(disMineFlag)
                        gridArray[i][j]->setIcon(QIcon(":/res/mine.png"));
                    else
                        gridArray[i][j]->setIcon(QIcon(":/res/flag.png"));
                }
            }
        }
        if(disMineFlag)
            disMineFlag = false;
        else
            disMineFlag = true;
    });

    //放置一个label当游戏结束或者胜利时阻挡继续点击
    label = new QLabel(this);
    label->move(-200, -200);

    //默认为初级难度
    //更新雷数
    isFirstClicked = true;
    mineTotal = level1_mine;
    this->startMine(level1_row, level1_col);

}
//初始化 雷区 函数
//传入雷区的 行数 和 列数
void MainWindow::startMine(int numRow, int numCol)
{
    currentRow = numRow;
    currentCol = numCol;
    //设置页面大小
    main_wide = numCol * mine_wide_height + left_right_dis * 2;
    main_height = numRow * mine_wide_height + top_bottom_dis * 2;
    setFixedSize(main_wide, main_height);
    //设置窗口位置
    this->move((sceneWidth - main_wide) * 0.5, (sceneHeigth - main_height) * 0.5 - 50);
    //设置笑脸位置
    btn_restart->move(main_wide * 0.5 - mine_wide_height * 0.5, 34);
    btn_restart->setIcon(QIcon(":/res/smile.png"));
    //设置LCD显示位置
    lcdNum->setGeometry(10, 30, 80, 40);
    lcdTime->setGeometry(main_wide - 80 - 10, 30, 80, 40);
    //设置LCD值
    lcdNum->display(mineTotal);
    lcdTime->display(0);
    //旗子置零 时间置零
    flagNum = 0;
    timeNum = 0;
    isStartTimer = false;
    isFirstClicked = true;
    isWiner = false;
    //停止定时器
    timer1->stop();
    timer2->stop();

    for(int i = 0; i < numRow; i++)
    {
        for(int j = 0; j < numCol; j++)
        {
            //qDebug() << i * numCol + j;
            Grid * mine = new Grid;
            mine->setParent(this);
            //设置雷位置
            mine->move(left_right_dis + j * mine_wide_height, top_bottom_dis + i * mine_wide_height + 30);
            //显示
            mine->show();

            //记录雷
            gridArray[i][j] = mine;
            mine->mine_row = i;
            mine->mine_col = j;
            //左键点击
            connect(mine, &Grid::clicked, [=](){
                //翻转格子
                //未被翻转且没有旗子 可翻转
                if(!mine->isFlag && !mine->isClicked)
                {
                    mine->isClicked = true;
                    //为第一次点击 即生成雷
                    if(isFirstClicked)
                    {
                        isFirstClicked = false;
                        buildMine(mine);

                        if(!isStartTimer)
                        {
                            //开始计时
                            timer1->start(1000);
                            isStartTimer = true;
                        }
                    }
                    //判断是否为雷
                    if(mine->isMine)
                    {
                        //游戏结束
                        this->gameOver(mine);
                    }
                    else
                    {
                        //翻开格子 显示周围雷数 若没有雷 继续打开周围格子
                        this->turnGrid(mine);
                        //判断是否获胜
                        this->isWin();
                    }
                }
            });
            //右键点击
            connect(mine, &Grid::playFlag, [=](){
                if(!isStartTimer)
                {
                    //开始计时
                    timer1->start(1000);
                    isStartTimer = true;
                }
                if(mine->isFlag)
                {
                    if(flagNum > 0)
                    {
                        flagNum--;
                        mine->setIcon(QIcon(":/res/mineBk.png"));
                        mine->isFlag = false;
                        lcdNum->display(mineTotal - flagNum);
                    }
                }
                else
                {
                    if(flagNum != mineTotal)
                    {
                        flagNum++;
                        mine->setIcon(QIcon(":/res/flag.png"));
                        mine->isFlag = true;
                        lcdNum->display(mineTotal - flagNum);
                    }
                }
            });
        }
    }
}
//清空
void MainWindow::del_array()
{
    for(int i = 0; i < rowMax; i++)
    {
        for(int j = 0; j < colMax; j++)
        {
            if(gridArray[i][j] != nullptr)
                delete gridArray[i][j];
            gridArray[i][j] = nullptr;
        }
    }
}
//生成雷（参数为第一个点击格子的地址 生成雷时排除这个格子）
void MainWindow::buildMine(Grid * grid)
{
    int numArr[mineTotal];
    int temp = -1;
    int ttt;
    //点击格子的“序号”
    temp = grid->mine_row * currentCol + grid->mine_col;
    //生成 mineTotal 个 0 ~ （currentRow * currentCol- 1） 的随机数
    for(int i = 0; i < mineTotal; i++)
    {
        ttt = QRandomGenerator::global()->bounded(currentRow * currentCol);
        if(temp != ttt)
        {
            numArr[i] = ttt;
            //判断是否重复
            for(int j = 0; j < i; j++)
            {
                //有重复即重新生成
                if(numArr[j] == numArr[i])
                {
                    i--;
                    break;
                }
            }
        }
        else
            i--;
    }
    //根据生成数组放置雷
    for(int i = 0; i < mineTotal; i++)
    {
        gridArray[numArr[i] / currentCol][numArr[i] % currentCol]->isMine = true;
    }
}
//游戏结束 点到雷（参数为点击的位置 显示为红色雷）
void MainWindow::gameOver(Grid * grid)
{
    //停止定时器
    timer1->stop();
    //设置为赢脸 哭脸
    if(isWiner)
        btn_restart->setIcon(QIcon(":/res/win.png"));
    else
        btn_restart->setIcon(QIcon(":/res/nosmile.png"));
    //翻转所有格子
    for(int i = 0; i < currentRow; i++)
    {
        for(int j = 0; j < currentCol; j++)
        {
            if(gridArray[i][j] == grid)
                gridArray[i][j]->setIcon(QIcon(":/res/mineRed.png"));
            else
            {
                if(gridArray[i][j]->isMine)
                {
                    if(gridArray[i][j]->isFlag)
                        gridArray[i][j]->setIcon(QIcon(":/res/flag.png"));
                    else
                        gridArray[i][j]->setIcon(QIcon(":/res/mine.png"));
                }
            }
        }
    }
    //游戏结束 循环显示放了旗子有雷的格子
    disMineFlag = true;
    timer2->start(700);

    //放置一个label阻挡继续点击
    label->setGeometry(left_right_dis - 5, top_bottom_dis + 30 - 5, currentCol * mine_wide_height + 10, currentRow * mine_wide_height + 10);
    label->raise();
    label->show();
}
//翻开格子
void MainWindow::turnGrid(Grid * grid)
{
    int mineNum = 0;
    //判断周围八格是否有雷
    //左
    if(grid->mine_col - 1 >= 0)
        if(gridArray[grid->mine_row][grid->mine_col - 1]->isMine)
            mineNum++;
    //上左
    if((grid->mine_row - 1 >= 0) && (grid->mine_col - 1 >= 0))
        if(gridArray[grid->mine_row - 1][grid->mine_col - 1]->isMine)
            mineNum++;
    //上
    if(grid->mine_row - 1 >= 0)
        if(gridArray[grid->mine_row - 1][grid->mine_col]->isMine)
            mineNum++;
    //上右
    if((grid->mine_row - 1 >= 0) && (grid->mine_col + 2 <= currentCol))
        if(gridArray[grid->mine_row - 1][grid->mine_col + 1]->isMine)
            mineNum++;
    //右
    if(grid->mine_col + 2 <= currentCol)
        if(gridArray[grid->mine_row][grid->mine_col + 1]->isMine)
            mineNum++;
    //下右
    if((grid->mine_row + 2 <= currentRow) && (grid->mine_col + 2 <= currentCol))
        if(gridArray[grid->mine_row + 1][grid->mine_col + 1]->isMine)
            mineNum++;
    //下
    if(grid->mine_row + 2 <= currentRow)
        if(gridArray[grid->mine_row + 1][grid->mine_col]->isMine)
            mineNum++;
    //下左
    if((grid->mine_row + 2 <= currentRow) && (grid->mine_col - 1 >= 0))
        if(gridArray[grid->mine_row + 1][grid->mine_col - 1]->isMine)
            mineNum++;

    //有雷即显示雷数
    if(mineNum > 0)
    {
        QString str = QString(":/res/0%1.png").arg(mineNum);
        grid->setIcon(QIcon(str));
    }
    else
    {
        //当周围八格没有雷时 打开周围的格子
        grid->setIcon(QIcon(":/res/mineBBk.png"));
        //左
        if(grid->mine_col - 1 >= 0)
            emit gridArray[grid->mine_row][grid->mine_col - 1]->clicked();
        //上左
        if((grid->mine_row - 1 >= 0) && (grid->mine_col - 1 >= 0))
            emit gridArray[grid->mine_row - 1][grid->mine_col - 1]->clicked();
        //上
        if(grid->mine_row - 1 >= 0)
            emit gridArray[grid->mine_row - 1][grid->mine_col]->clicked();
        //上右
        if((grid->mine_row - 1 >= 0) && (grid->mine_col + 2 <= currentCol))
            emit gridArray[grid->mine_row - 1][grid->mine_col + 1]->clicked();
        //右
        if(grid->mine_col + 2 <= currentCol)
            emit gridArray[grid->mine_row][grid->mine_col + 1]->clicked();
        //下右
        if((grid->mine_row + 2 <= currentRow) && (grid->mine_col + 2 <= currentCol))
            emit gridArray[grid->mine_row + 1][grid->mine_col + 1]->clicked();
        //下
        if(grid->mine_row + 2 <= currentRow)
            emit gridArray[grid->mine_row + 1][grid->mine_col]->clicked();
        //下左
        if((grid->mine_row + 2 <= currentRow) && (grid->mine_col - 1 >= 0))
            emit gridArray[grid->mine_row + 1][grid->mine_col - 1]->clicked();
    }
}
//判断是否获胜
void MainWindow::isWin()
{
    for(int i = 0; i < currentRow; i++)
    {
        for(int j = 0; j < currentCol; j++)
        {
            if(!gridArray[i][j]->isClicked && !gridArray[i][j]->isMine)
                return;
        }
    }
    //胜利
    this->isWiner = true;
    this->gameOver();
}

MainWindow::~MainWindow()
{
    delete ui;
}

